home *** CD-ROM | disk | FTP | other *** search
/ Aminet 5 / Aminet 5 - March 1995.iso / Aminet / comm / tcp / ATCP_src_22.lha / AmiTCP-2.2 / src / amitcp / net / if.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-06  |  22.0 KB  |  875 lines

  1. RCS_ID_C="$Id: if.c,v 1.21 1993/10/29 02:00:17 ppessi Exp $";
  2. /*
  3.  * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>,
  4.  *                    Helsinki University of Technology, Finland.
  5.  *                    All rights reserved.
  6.  *
  7.  * if.c --- Generic Network Interface Routines
  8.  *
  9.  * Last modified: Thu Oct 28 22:38:01 1993 ppessi
  10.  *
  11.  * HISTORY
  12.  * $Log: if.c,v $
  13.  * Revision 1.21  1993/10/29  02:00:17  ppessi
  14.  * Added SIOCGARPT ioctl.
  15.  *
  16.  * Revision 1.21  1993/10/29  02:00:17  ppessi
  17.  * Added SIOCGARPT ioctl.
  18.  *
  19.  * Revision 1.20  1993/09/19  21:14:18  jraja
  20.  * Fixed a bug with '/' placement in ifconf().
  21.  *
  22.  * Revision 1.19  1993/09/09  23:45:36  ppessi
  23.  * Changed the interface name format returned by SIOCGIFCONF.
  24.  *
  25.  * Revision 1.18  1993/06/04  11:16:15  jraja
  26.  * Fixes for first public release.
  27.  *
  28.  * Revision 1.17  1993/05/16  21:09:43  ppessi
  29.  * RCS version changed.
  30.  *
  31.  * Revision 1.16  1993/04/24  23:42:37  jraja
  32.  * Removed few #ifdef AMITCP's.
  33.  *
  34.  * Revision 1.15  93/04/24  23:20:01  23:20:01  jraja (Jarno Tapio Rajahalme)
  35.  * Removed #ifdef NOALIGN, now using straight structure copies.
  36.  * 
  37.  * Revision 1.14  93/04/19  02:09:58  02:09:58  ppessi (Pekka Pessi)
  38.  * arpioctl() declared here instead of protos file.
  39.  * 
  40.  * Revision 1.13  93/04/13  22:19:02  22:19:02  jraja (Jarno Tapio Rajahalme)
  41.  * Added casts to the pr_usrreq calls to comply with the prototype.
  42.  * 
  43.  * Revision 1.12  93/04/11  22:20:06  22:20:06  jraja (Jarno Tapio Rajahalme)
  44.  * Removed unnecessary casts from function pointers, Changed ellipses to 
  45.  * prototypes.
  46.  * 
  47.  * Revision 1.11  93/04/05  17:45:06  17:45:06  jraja (Jarno Tapio Rajahalme)
  48.  * Changed spl storage variables to spl_t.
  49.  * Changed every .c file to use conf.h.
  50.  * 
  51.  * Revision 1.10  93/03/19  14:30:32  14:30:32  too (Tomi Ollila)
  52.  * Code changes at night 17-18 March 1993
  53.  * 
  54.  * Revision 1.9  93/03/12  23:54:16  23:54:16  ppessi (Pekka Pessi)
  55.  * Cancelled if_down() kludge.
  56.  * 
  57.  * Revision 1.1  93/03/12  05:26:56  05:26:56  ppessi (Pekka Pessi)
  58.  * pulled if_down() to if_sana.c; Final Kludge to sana_up/down()
  59.  * #ifdef'ed if_dl.h and if_types.h from includes
  60.  * 
  61.  * Revision 1.8  93/03/09  17:56:17  17:56:17  ppessi (Pekka Pessi)
  62.  * Fixed bug with unit number conversion.
  63.  * 
  64.  * Revision 1.1  93/03/09  17:55:36  17:55:36  ppessi (Pekka Pessi)
  65.  * Initial revision
  66.  * 
  67.  * Revision 1.7  93/03/05  19:50:37  19:50:37  jraja (Jarno Tapio Rajahalme)
  68.  * Fixed includes (again).
  69.  * 
  70.  * Revision 1.6  93/03/05  03:11:56  03:11:56  ppessi (Pekka Pessi)
  71.  * Compiles with SASC. Initial test version
  72.  * 
  73.  * Revision 1.5  93/02/28  21:34:42  21:34:42  ppessi (Pekka Pessi)
  74.  * Changed device name semantics (now devs:foo/xx/00 instead of xx00)
  75.  * Kludged IFF_UP passing to if_ioctl() call.
  76.  * 
  77.  * Revision 1.4  93/02/24  10:22:52  10:22:52  jraja (Jarno Tapio Rajahalme)
  78.  * Fixed timeout().
  79.  * 
  80.  * Revision 1.3  93/02/19  15:38:07  15:38:07  jraja (Jarno Tapio Rajahalme)
  81.  * Changed ifioctl's proc argument to SocketBase.
  82.  * 
  83.  * Revision 1.2  92/11/20  14:42:42  14:42:42  jraja (Jarno Tapio Rajahalme)
  84.  * added #ifndef AMITCP's to get this compile somehow
  85.  * 
  86.  * Revision 1.1  92/11/20  13:31:58  13:31:58  jraja (Jarno Tapio Rajahalme)
  87.  * Initial revision
  88.  */
  89.  
  90. /* 
  91.  * Mach Operating System
  92.  * Copyright (c) 1992 Carnegie Mellon University
  93.  * All Rights Reserved.
  94.  * 
  95.  * Permission to use, copy, modify and distribute this software and its
  96.  * documentation is hereby granted, provided that both the copyright
  97.  * notice and this permission notice appear in all copies of the
  98.  * software, derivative works or modified versions, and any portions
  99.  * thereof, and that both notices appear in supporting documentation.
  100.  * 
  101.  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  102.  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  103.  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  104.  * 
  105.  * Carnegie Mellon requests users of this software to return to
  106.  * 
  107.  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
  108.  *  School of Computer Science
  109.  *  Carnegie Mellon University
  110.  *  Pittsburgh PA 15213-3890
  111.  * 
  112.  * any improvements or extensions that they make and grant Carnegie Mellon 
  113.  * the rights to redistribute these changes.
  114.  */
  115. /*
  116.  * HISTORY
  117.  * Log:    if.c,v
  118.  * Revision 2.1  92/04/21  17:13:56  rwd
  119.  * BSDSS
  120.  * 
  121.  *
  122.  */
  123.  
  124. /*
  125.  * Copyright (c) 1980, 1986 Regents of the University of California.
  126.  * All rights reserved.
  127.  *
  128.  * Redistribution and use in source and binary forms, with or without
  129.  * modification, are permitted provided that the following conditions
  130.  * are met:
  131.  * 1. Redistributions of source code must retain the above copyright
  132.  *    notice, this list of conditions and the following disclaimer.
  133.  * 2. Redistributions in binary form must reproduce the above copyright
  134.  *    notice, this list of conditions and the following disclaimer in the
  135.  *    documentation and/or other materials provided with the distribution.
  136.  * 3. All advertising materials mentioning features or use of this software
  137.  *    must display the following acknowledgement:
  138.  *    This product includes software developed by the University of
  139.  *    California, Berkeley and its contributors.
  140.  * 4. Neither the name of the University nor the names of its contributors
  141.  *    may be used to endorse or promote products derived from this software
  142.  *    without specific prior written permission.
  143.  *
  144.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  145.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  146.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  147.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  148.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  149.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  150.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  151.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  152.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  153.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  154.  * SUCH DAMAGE.
  155.  *
  156.  *    @(#)if.c    7.14 (Berkeley) 4/20/91
  157.  */
  158.  
  159. #include <conf.h>
  160.  
  161. #include <sys/param.h>
  162. #include <sys/malloc.h>
  163. #include <sys/mbuf.h>
  164. #include <sys/systm.h>
  165. #include <sys/socket.h>
  166. #include <sys/socketvar.h>
  167. #include <sys/protosw.h>
  168. #include <sys/kernel.h>
  169. #include <sys/ioctl.h>
  170. #include <sys/synch.h>
  171.  
  172. #include <net/if.h>
  173. #include <net/if_dl.h>
  174.  
  175. #include <net/if_protos.h>
  176. #include <kern/uipc_domain_protos.h>
  177.  
  178. static char *sprint_d(u_int n, char *buf, int buflen);
  179. int    ifqmaxlen = IFQ_MAXLEN;
  180.  
  181. struct    ifnet *ifnet = NULL;
  182.  
  183. /*
  184.  * Network interface utility routines.
  185.  *
  186.  * Routines with ifa_ifwith* names take sockaddr *'s as
  187.  * parameters.
  188.  */
  189.  
  190. void ifinit(void)
  191. {
  192.     register struct ifnet *ifp;
  193.  
  194.     for (ifp = ifnet; ifp; ifp = ifp->if_next)
  195.         if (ifp->if_snd.ifq_maxlen == 0)
  196.             ifp->if_snd.ifq_maxlen = ifqmaxlen;
  197.     if_slowtimo();
  198. }
  199.  
  200. #ifdef vax
  201. /*
  202.  * Call each interface on a Unibus reset.
  203.  */
  204. ifubareset(uban)
  205.     int uban;
  206. {
  207.     register struct ifnet *ifp;
  208.  
  209.     for (ifp = ifnet; ifp; ifp = ifp->if_next)
  210.         if (ifp->if_reset)
  211.             (*ifp->if_reset)(ifp->if_unit, uban);
  212. }
  213. #endif
  214.  
  215. int if_index = 0;
  216. struct ifaddr **ifnet_addrs;
  217. static char *sprint_d();
  218.  
  219. /*
  220.  * Attach an interface to the
  221.  * list of "active" interfaces.
  222.  */
  223. void
  224. if_attach(ifp)
  225.      struct ifnet *ifp;
  226. {
  227.     unsigned socksize, ifasize;
  228.     int namelen, unitlen;
  229.     char workbuf[12], *unitname;
  230.     register struct ifnet **p = &ifnet;
  231.     register struct sockaddr_dl *sdl;
  232.     register struct ifaddr *ifa;
  233.     static int if_indexlim = 8;
  234.  
  235.     while (*p)
  236.         p = &((*p)->if_next);
  237.     *p = ifp;
  238.     ifp->if_index = ++if_index;
  239.     if (ifnet_addrs == 0 || if_index >= if_indexlim) {
  240.         unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
  241.         struct ifaddr **q = (struct ifaddr **)
  242.                     bsd_malloc(n, M_IFADDR, M_WAITOK);
  243.         if (ifnet_addrs) {
  244.             aligned_bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
  245.             bsd_free((caddr_t)ifnet_addrs, M_IFADDR);
  246.         }
  247.         ifnet_addrs = q;
  248.     }
  249.     /*
  250.      * create a Link Level name for this device
  251.      */
  252. #ifdef AMITCP
  253.     /* Exec device name can contain digits, workaround with slash */
  254.     unitname = sprint_d((u_int)ifp->if_unit, 
  255.                 workbuf + 1, 
  256.                 sizeof(workbuf) - 1);
  257.     *--unitname = '/';
  258. #else
  259.     unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf));
  260. #endif
  261.     namelen = strlen(ifp->if_name);
  262.         unitlen = strlen(unitname);
  263. #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
  264.     socksize = _offsetof(struct sockaddr_dl, sdl_data[0]) +
  265.                    unitlen + namelen + ifp->if_addrlen;
  266. #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
  267.     socksize = ROUNDUP(socksize);
  268.     if (socksize < sizeof(*sdl))
  269.         socksize = sizeof(*sdl);
  270.     ifasize = sizeof(*ifa) + 2 * socksize;
  271.     ifa = (struct ifaddr *)bsd_malloc(ifasize, M_IFADDR, M_WAITOK);
  272.     if (ifa == 0)
  273.         return;
  274.     ifnet_addrs[if_index - 1] = ifa;
  275.     aligned_bzero((caddr_t)ifa, ifasize);
  276.     sdl = (struct sockaddr_dl *)(ifa + 1);
  277.     ifa->ifa_addr = (struct sockaddr *)sdl;
  278.     ifa->ifa_ifp = ifp;
  279.     sdl->sdl_len = socksize;
  280.     sdl->sdl_family = AF_LINK;
  281.     bcopy(ifp->if_name, sdl->sdl_data, namelen);
  282.     bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen);
  283.     sdl->sdl_nlen = (namelen += unitlen);
  284.     sdl->sdl_index = ifp->if_index;
  285.     sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
  286.     ifa->ifa_netmask = (struct sockaddr *)sdl;
  287.     sdl->sdl_len = socksize - ifp->if_addrlen;
  288.     while (namelen != 0)
  289.         sdl->sdl_data[--namelen] = (char)0xff;
  290.     ifa->ifa_next = ifp->if_addrlist;
  291.     ifa->ifa_rtrequest = link_rtrequest;
  292.     ifp->if_addrlist = ifa;
  293. }
  294. /*
  295.  * Locate an interface based on a complete address.
  296.  */
  297. /*ARGSUSED*/
  298. struct ifaddr *
  299. ifa_ifwithaddr(addr)
  300.     register struct sockaddr *addr;
  301. {
  302.     register struct ifnet *ifp;
  303.     register struct ifaddr *ifa;
  304.  
  305. #define    equal(a1, a2) \
  306.   (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
  307.     for (ifp = ifnet; ifp; ifp = ifp->if_next)
  308.         for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
  309.         if (ifa->ifa_addr->sa_family != addr->sa_family)
  310.             continue;
  311.         if (equal(addr, ifa->ifa_addr))
  312.             return (ifa);
  313.         if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
  314.             equal(ifa->ifa_broadaddr, addr))
  315.             return (ifa);
  316.     }
  317.     return ((struct ifaddr *)0);
  318. }
  319. /*
  320.  * Locate the point to point interface with a given destination address.
  321.  */
  322. /*ARGSUSED*/
  323. struct ifaddr *
  324. ifa_ifwithdstaddr(addr)
  325.     register struct sockaddr *addr;
  326. {
  327.     register struct ifnet *ifp;
  328.     register struct ifaddr *ifa;
  329.  
  330.     for (ifp = ifnet; ifp; ifp = ifp->if_next) 
  331.         if (ifp->if_flags & IFF_POINTOPOINT)
  332.         for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
  333.             if (ifa->ifa_addr->sa_family != addr->sa_family)
  334.                 continue;
  335.             if (equal(addr, ifa->ifa_dstaddr))
  336.                 return (ifa);
  337.     }
  338.     return ((struct ifaddr *)0);
  339. }
  340.  
  341. /*
  342.  * Find an interface on a specific network.  If many, choice
  343.  * is first found.
  344.  */
  345. struct ifaddr *
  346. ifa_ifwithnet(addr)
  347.     struct sockaddr *addr;
  348. {
  349.     register struct ifnet *ifp;
  350.     register struct ifaddr *ifa;
  351.     u_int af = addr->sa_family;
  352.  
  353.     if (af >= AF_MAX)
  354.         return (0);
  355.     if (af == AF_LINK) {
  356.         register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
  357.         if (sdl->sdl_index && sdl->sdl_index <= if_index)
  358.         return (ifnet_addrs[sdl->sdl_index - 1]);
  359.     }
  360.     for (ifp = ifnet; ifp; ifp = ifp->if_next)
  361.         for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
  362.         register char *cp, *cp2, *cp3;
  363.         register char *cplim;
  364.         if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0)
  365.             continue;
  366.         cp = addr->sa_data;
  367.         cp2 = ifa->ifa_addr->sa_data;
  368.         cp3 = ifa->ifa_netmask->sa_data;
  369.         cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
  370.         for (; cp3 < cplim; cp3++)
  371.             if ((*cp++ ^ *cp2++) & *cp3)
  372.                 break;
  373.         if (cp3 == cplim)
  374.             return (ifa);
  375.         }
  376.     return ((struct ifaddr *)0);
  377. }
  378.  
  379. /*
  380.  * Find an interface using a specific address family
  381.  */
  382. struct ifaddr *
  383. ifa_ifwithaf(af)
  384.     register int af;
  385. {
  386.     register struct ifnet *ifp;
  387.     register struct ifaddr *ifa;
  388.  
  389.     for (ifp = ifnet; ifp; ifp = ifp->if_next)
  390.         for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
  391.         if (ifa->ifa_addr->sa_family == af)
  392.             return (ifa);
  393.     return ((struct ifaddr *)0);
  394. }
  395.  
  396. /*
  397.  * Find an interface address specific to an interface best matching
  398.  * a given address.
  399.  */
  400. struct ifaddr *
  401. ifaof_ifpforaddr(addr, ifp)
  402.     struct sockaddr *addr;
  403.     register struct ifnet *ifp;
  404. {
  405.     register struct ifaddr *ifa;
  406.     register char *cp, *cp2, *cp3;
  407.     register char *cplim;
  408.     struct ifaddr *ifa_maybe = 0;
  409.     u_int af = addr->sa_family;
  410.  
  411.     if (af >= AF_MAX)
  412.         return (0);
  413.     for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
  414.         if (ifa->ifa_addr->sa_family != af)
  415.             continue;
  416.         ifa_maybe = ifa;
  417.         if (ifa->ifa_netmask == 0) {
  418.             if (equal(addr, ifa->ifa_addr) ||
  419.                 (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
  420.                 return (ifa);
  421.             continue;
  422.         }
  423.         cp = addr->sa_data;
  424.         cp2 = ifa->ifa_addr->sa_data;
  425.         cp3 = ifa->ifa_netmask->sa_data;
  426.         cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
  427.         for (; cp3 < cplim; cp3++)
  428.             if ((*cp++ ^ *cp2++) & *cp3)
  429.                 break;
  430.         if (cp3 == cplim)
  431.             return (ifa);
  432.     }
  433.     return (ifa_maybe);
  434. }
  435. #include <net/route.h>
  436. /*
  437.  * Default action when installing a route with a Link Level gateway.
  438.  * Lookup an appropriate real ifa to point to.
  439.  * This should be moved to /sys/net/link.c eventually.
  440.  */
  441. void
  442. link_rtrequest(int cmd, register struct rtentry *rt, struct sockaddr *sa)
  443. {
  444.     register struct ifaddr *ifa;
  445.     struct sockaddr *dst;
  446.     struct ifnet *ifp;
  447.  
  448.     if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
  449.         ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
  450.         return;
  451.     if (ifa = ifaof_ifpforaddr(dst, ifp)) {
  452.         rt->rt_ifa = ifa;
  453.         if (ifa->ifa_rtrequest && 
  454.             ifa->ifa_rtrequest != link_rtrequest)
  455.             ifa->ifa_rtrequest(cmd, rt, sa);
  456.     }
  457. }
  458.  
  459. /*
  460.  * Mark an interface down and notify protocols of
  461.  * the transition.
  462.  * NOTE: must be called at splnet or eqivalent.
  463.  */
  464. void
  465. if_down(ifp)
  466.     register struct ifnet *ifp;
  467. {
  468.     register struct ifaddr *ifa;
  469.  
  470.     ifp->if_flags &= ~IFF_UP;
  471.     for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
  472.         pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
  473.     if_qflush(&ifp->if_snd);
  474. }
  475.  
  476. /*
  477.  * Flush an interface queue.
  478.  */
  479. void
  480. if_qflush(ifq)
  481.     register struct ifqueue *ifq;
  482. {
  483.     register struct mbuf *m, *n;
  484.  
  485.     n = ifq->ifq_head;
  486.     while (m = n) {
  487.         n = m->m_act;
  488.         m_freem(m);
  489.     }
  490.     ifq->ifq_head = 0;
  491.     ifq->ifq_tail = 0;
  492.     ifq->ifq_len = 0;
  493. }
  494.  
  495. /*
  496.  * Handle interface watchdog timer routines.  Called
  497.  * from softclock, we decrement timers (if set) and
  498.  * call the appropriate interface routine on expiration.
  499.  */
  500. void
  501. if_slowtimo()
  502. {
  503.   /*
  504.    * This routine is disabled since there are 
  505.    * no timeouts in our network interfaces
  506.    */
  507. #ifndef AMITCP            
  508.     register struct ifnet *ifp;
  509.     spl_t s = splimp();
  510.  
  511.     for (ifp = ifnet; ifp; ifp = ifp->if_next) {
  512.         if (ifp->if_timer == 0 || --ifp->if_timer)
  513.             continue;
  514.         if (ifp->if_watchdog)
  515.             (*ifp->if_watchdog)(ifp->if_unit);
  516.     }
  517.     splx(s);
  518. #ifndef AMITCP
  519.     /*
  520.      * Timeouts are scheduled from amiga_time.c in AmiTCP/IP.
  521.      */
  522.     timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ);
  523. #endif
  524. #endif
  525. }
  526.  
  527. /*
  528.  * Map interface name to
  529.  * interface structure pointer.
  530.  */
  531. struct ifnet *
  532. ifunit(name)
  533.     register char *name;
  534. {
  535.     register char *cp;
  536.     register struct ifnet *ifp;
  537.     int unit;
  538.     unsigned len;
  539.     char *ep, c;
  540.  
  541. #ifdef AMITCP
  542.     /* AmigaTCP/IP uses the slash as unit number separator 
  543.      * because Exec device name may contain digits.
  544.      */
  545.     char *up;
  546.     cp = ep = name - 1;
  547.     /* Find pathpart */
  548.     for (up = name; *up; up++) 
  549.         if (*up == '/' || *up == ':') {
  550.             cp = ep;
  551.             ep = up;
  552.         }
  553.     /* Name is too long, or there is no unit number */
  554.     if (up >= cp + IFNAMSIZ || cp == ep)    
  555.         return ((struct ifnet *)0);
  556.     cp++;
  557.     /*
  558.      * cp points first char in device name,
  559.      * ep to unit number separator ('/')
  560.      * and up to NUL ('\0') at the end of string
  561.      */
  562.     len = ep - cp;
  563.     c = *ep;
  564.     *ep = '\0';        /* sentinel */
  565.     for (unit = 0, up--; *up >= '0' && *up <= '9'; up--) 
  566.         unit = unit * 10 + *up - '0';
  567.     *ep = c;
  568.     if (up != ep) {
  569.         return NULL;
  570.     }
  571.     /* Pathpart is not included in search */
  572.     for (ifp = ifnet; ifp; ifp = ifp->if_next) {
  573.         if (bcmp(ifp->if_name, cp, len))
  574.             continue;
  575.         if (unit == ifp->if_unit)
  576.             break;
  577.     }
  578. #else
  579.     for (cp = name; cp < name + IFNAMSIZ && *cp; cp++)
  580.         if (*cp >= '0' && *cp <= '9')
  581.             break;
  582.     if (*cp == '\0' || cp == name + IFNAMSIZ)
  583.         return ((struct ifnet *)0);
  584.     /*
  585.      * Save first char of unit, and pointer to it,
  586.      * so we can put a null there to avoid matching
  587.      * initial substrings of interface names.
  588.      */
  589.     len = cp - name + 1;
  590.     c = *cp;
  591.     ep = cp;
  592.     for (unit = 0; *cp >= '0' && *cp <= '9'; )
  593.         unit = unit * 10 + *cp++ - '0';
  594.     *ep = 0;
  595.  
  596.     for (ifp = ifnet; ifp; ifp = ifp->if_next) {
  597.         if (bcmp(ifp->if_name, name, len))
  598.             continue;
  599.         if (unit == ifp->if_unit)
  600.             break;
  601.     }
  602.     *ep = c;
  603. #endif
  604.     {
  605.         extern struct ifnet *iface_find(char *);
  606.         if (ifp == 0)
  607.         ifp = iface_find(name);
  608.     }
  609.     return (ifp);
  610. }
  611.  
  612. /*
  613.  * Interface ioctls.
  614.  */
  615. int
  616. ifioctl(so, cmd, data)
  617.     struct socket *so;
  618.     int cmd;
  619.     caddr_t data;
  620. {
  621.     register struct ifnet *ifp;
  622.     register struct ifreq *ifr;
  623. #ifndef AMITCP
  624.     int error;
  625. #endif
  626.     extern int arpioctl(int cmd, caddr_t data);
  627.  
  628.     switch (cmd) {
  629.  
  630.     case SIOCGIFCONF:
  631.     case OSIOCGIFCONF:
  632.         return (ifconf(cmd, data));
  633.  
  634. #if INET && NETHER > 0
  635.     case SIOCSARP:
  636.     case SIOCDARP:
  637. #ifndef AMITCP /* no protection on AmigaOS */
  638.         if (error = suser(p->p_ucred, &p->p_acflag))
  639.             return (error);
  640.         /* FALL THROUGH */
  641. #else
  642.     case SIOCGARPT:
  643. #endif /* AMITCP */
  644.     case SIOCGARP:
  645.     case OSIOCGARP:
  646.         return (arpioctl(cmd, data));
  647. #endif
  648.     }
  649.     ifr = (struct ifreq *)data;
  650.     ifp = ifunit(ifr->ifr_name);
  651.     if (ifp == 0)
  652.         return (ENXIO);
  653.     switch (cmd) {
  654.  
  655.     case SIOCGIFFLAGS:
  656.         ifr->ifr_flags = ifp->if_flags;
  657.         break;
  658.  
  659.     case SIOCGIFMETRIC:
  660.         ifr->ifr_metric = ifp->if_metric;
  661.         break;
  662.  
  663.     case SIOCSIFFLAGS:
  664. #ifndef AMITCP /* no protection on AmigaOS */
  665.         if (error = suser(p->p_ucred, &p->p_acflag))
  666.             return (error);
  667. #endif /* AMITCP */
  668.         /* if_down() is kludged for Sana-II driver ioctl */
  669.         if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
  670.             spl_t s = splimp();
  671.             if_down(ifp);
  672.             splx(s);
  673.         }
  674.         ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
  675.             (ifr->ifr_flags &~ IFF_CANTCHANGE);
  676.         if (ifp->if_ioctl)
  677.             (void) (*ifp->if_ioctl)(ifp, cmd, data);
  678.         break;
  679.  
  680.     case SIOCSIFMETRIC:
  681. #ifndef AMITCP /* no protection on AmigaOS */
  682.         if (error = suser(p->p_ucred, &p->p_acflag))
  683.             return (error);
  684. #endif /* AMITCP */
  685.         ifp->if_metric = ifr->ifr_metric;
  686.         break;
  687.  
  688.     default:
  689.         if (so->so_proto == 0)
  690.             return (EOPNOTSUPP);
  691. #ifndef COMPAT_43
  692.         return ((*so->so_proto->pr_usrreq)(so,
  693.                            PRU_CONTROL,
  694.                            (struct mbuf *)cmd,
  695.                            (struct mbuf *)data,
  696.                            (struct mbuf *)ifp));
  697. #else
  698.         {
  699.         int ocmd = cmd;
  700.  
  701.         switch (cmd) {
  702.  
  703.         case SIOCSIFDSTADDR:
  704.         case SIOCSIFADDR:
  705.         case SIOCSIFBRDADDR:
  706.         case SIOCSIFNETMASK:
  707. #if BYTE_ORDER != BIG_ENDIAN
  708.             if (ifr->ifr_addr.sa_family == 0 &&
  709.                 ifr->ifr_addr.sa_len < 16) {
  710.                 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
  711.                 ifr->ifr_addr.sa_len = 16;
  712.             }
  713. #else
  714.             if (ifr->ifr_addr.sa_len == 0)
  715.                 ifr->ifr_addr.sa_len = 16;
  716. #endif
  717.             break;
  718.  
  719.         case OSIOCGIFADDR:
  720.             cmd = SIOCGIFADDR;
  721.             break;
  722.  
  723.         case OSIOCGIFDSTADDR:
  724.             cmd = SIOCGIFDSTADDR;
  725.             break;
  726.  
  727.         case OSIOCGIFBRDADDR:
  728.             cmd = SIOCGIFBRDADDR;
  729.             break;
  730.  
  731.         case OSIOCGIFNETMASK:
  732.             cmd = SIOCGIFNETMASK;
  733.         }
  734.         error =  ((*so->so_proto->pr_usrreq)(so,
  735.                              PRU_CONTROL,
  736.                              (struct mbuf *)cmd,
  737.                              (struct mbuf *)data,
  738.                              (struct mbuf *)ifp));
  739.         switch (ocmd) {
  740.  
  741.         case OSIOCGIFADDR:
  742.         case OSIOCGIFDSTADDR:
  743.         case OSIOCGIFBRDADDR:
  744.         case OSIOCGIFNETMASK:
  745.             *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
  746.         }
  747.         return (error);
  748.  
  749.         }
  750. #endif
  751.     }
  752.     return (0);
  753. }
  754.  
  755. /*
  756.  * Return interface configuration
  757.  * of system.  List may be used
  758.  * in later ioctl's (above) to get
  759.  * other information.
  760.  */
  761. int
  762. ifconf(cmd, data)
  763.     int cmd;
  764.     caddr_t data;
  765. {
  766.     register struct ifconf *ifc = (struct ifconf *)data;
  767.     register struct ifnet *ifp = ifnet;
  768.     register struct ifaddr *ifa;
  769.     register char *cp, *ep;
  770.     struct ifreq ifr, *ifrp;
  771.     int space = ifc->ifc_len, error = 0;
  772.  
  773.     ifrp = ifc->ifc_req;
  774. #ifndef AMITCP
  775.     ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2;
  776. #endif
  777.     for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
  778. #ifdef AMITCP
  779.         ep = sprint_d(ifp->if_unit, ifr.ifr_name, sizeof(ifr.ifr_name));
  780.         *--ep = '/';
  781.         /* Copy the interface name into ifr */
  782.         bcopy(ifp->if_name, ifr.ifr_name, ep - ifr.ifr_name);
  783.         /* Find the end of interface name */
  784.         for (cp = ifr.ifr_name; cp < ep && *cp; cp++)
  785.             ;
  786.         /* Append unit number to it */
  787.         for (; *cp = *ep; cp++, ep++)
  788.             ;
  789. #else
  790.         bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2);
  791.         for (cp = ifr.ifr_name; cp < ep && *cp; cp++)
  792.             ;
  793.         *cp++ = '0' + ifp->if_unit; *cp = '\0';
  794. #endif
  795.         if ((ifa = ifp->if_addrlist) == 0) {
  796.             aligned_bzero_const((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
  797. #ifdef AMITCP
  798.             *ifrp = ifr;
  799. #else
  800.             error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr));
  801.             if (error)
  802.                 break;
  803. #endif
  804.             space -= sizeof (ifr), ifrp++;
  805.         } else 
  806.             for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) {
  807.             register struct sockaddr *sa = ifa->ifa_addr;
  808. #ifdef COMPAT_43
  809.             if (cmd == OSIOCGIFCONF) {
  810.                 struct osockaddr *osa =
  811.                      (struct osockaddr *)&ifr.ifr_addr;
  812.                 ifr.ifr_addr = *sa;
  813.                 osa->sa_family = sa->sa_family;
  814.                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
  815.                         sizeof (ifr));
  816.                 ifrp++;
  817.             } else
  818. #endif
  819.             if (sa->sa_len <= sizeof(*sa)) {
  820.                 ifr.ifr_addr = *sa;
  821. #ifdef AMITCP
  822.                 *ifrp = ifr;
  823. #else
  824.                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
  825.                         sizeof (ifr));
  826. #endif
  827.                 ifrp++;
  828.             } else {
  829.                 space -= sa->sa_len - sizeof(*sa);
  830.                 if (space < sizeof (ifr))
  831.                     break;
  832. #ifdef AMITCP
  833.                 aligned_bcopy_const((caddr_t)&ifr, 
  834.                             (caddr_t)ifrp,
  835.                             sizeof (ifr.ifr_name));
  836.                 aligned_bcopy((caddr_t)sa,
  837.                       (caddr_t)&ifrp->ifr_addr, sa->sa_len);
  838. #else
  839.                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
  840.                         sizeof (ifr.ifr_name));
  841.                 if (error == 0)
  842.                     error = copyout((caddr_t)sa,
  843.                       (caddr_t)&ifrp->ifr_addr, sa->sa_len);
  844. #endif
  845.                 ifrp = (struct ifreq *)
  846.                     (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
  847.             }
  848. #ifndef AMITCP
  849.             if (error)
  850.                 break;
  851. #endif
  852.             space -= sizeof (ifr);
  853.         }
  854.     }
  855.     ifc->ifc_len -= space;
  856.     return (error);
  857. }
  858.  
  859. static char *
  860. sprint_d(n, buf, buflen)
  861.     u_int n;
  862.     char *buf;
  863.     int buflen;
  864. {
  865.     register char *cp = buf + buflen - 1;
  866.  
  867.     *cp = 0;
  868.     do {
  869.         cp--;
  870.         *cp = "0123456789"[n % 10];
  871.         n /= 10;
  872.     } while (n != 0);
  873.     return (cp);
  874. }
  875.